package com.woniuxy.project.campus.account.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.woniuxy.project.campus.CenteenCilnt;
import com.woniuxy.project.campus.account.dto.PageInfo;
import com.woniuxy.project.campus.account.dto.ResourceDto;
import com.woniuxy.project.campus.account.dto.UserCartInfo;
import com.woniuxy.project.campus.account.model.form.*;
import com.woniuxy.project.campus.account.mapper.RoleAccountMapper;
import com.woniuxy.project.campus.account.model.Account;
import com.woniuxy.project.campus.account.mapper.AccountMapper;
import com.woniuxy.project.campus.account.model.RoleAccount;
import com.woniuxy.project.campus.account.param.AddAShoppingCartParam;
import com.woniuxy.project.campus.account.param.LoginParam;
import com.woniuxy.project.campus.account.param.MerchantapplicationParam;
import com.woniuxy.project.campus.account.param.RegisterParam;
import com.woniuxy.project.campus.account.redisClint.RedisUtil;
import com.woniuxy.project.campus.account.service.AccountService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniuxy.project.campus.canteenModelform.SelectProShopInfo;
import com.woniuxy.project.campus.util.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 吴彦祖
 * @since 2025年02月17日
 */
@Service
public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> implements AccountService {
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private AccountMapper accountMapper;
    @Resource
    private PermissionServiceImpl permissionService;
    @Resource
    private RoleAccountMapper roleAccountMapper;
    @Resource
    private CenteenCilnt centeencilent;
    @Override
    public void smsRegistration(String mobile) throws Exception {
        QueryWrapper<Account> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone",mobile);
        if(accountMapper.selectOne(queryWrapper)!=null){
            throw new Exception("手机号码已注册,请直接登录");
        }
        //判断是否已经发送过验证码
        if(redisUtil.getString(RedisKey.getSendRegCodeKey(mobile))!=null){
            throw new Exception("一分钟内只能发送一次验证码，请稍后再试");
        }
        //判断24小时内发送验证码次数是否超过5次
        Long l = redisUtil.incrementCdoe(RedisKey.userCodeNumKey(mobile));
        if(l>5){
            throw new Exception("24小时内只能发送5次验证码，请稍后再试");
        }
        String api ="https://106.ihuyi.com/webservice/sms.php?method=Submit";
        String account="C09844997";
        String password="7e71a60be5b693f8258d7e987316f124";
        System.out.println("手机号"+mobile);
        System.out.println("api"+api);
        System.out.println("account"+account);
        System.out.println("password"+password);
        //使用hutool提供的Http工具发送请求
        HashMap<String, Object> params = new HashMap<>();
        params.put("account",account);
        params.put("password",password);
        params.put("mobile",mobile);
        params.put("format","json");
        String code=String.valueOf((int)(Math.random()*9000)+1000);
        System.out.println(code);
        String content="您的验证码是：" + code + "。请不要把验证码泄露给其他人。";
        params.put("content",content);

        //向第三方的接口发送请求
        HttpResponse response = HttpRequest.post(api).form(params).execute();
        String json = response.body();
        String resultCode = JSONUtil.parseObj(json).get("code").toString();
        System.out.println(resultCode);
        if("2".equals(resultCode)){
            redisUtil.set(RedisKey.getSendRegCodeKey(mobile),code,60*5*60*1000);
            redisUtil.incrementCdoe(RedisKey.userCodeNumKey(mobile));
            redisUtil.setExpire(RedisKey.userCodeNumKey(mobile), 24 * 60 * 60);
            System.out.println("短信验证码："+code);
        }else{
            throw new Exception("短信发送失败");
        }
    }

    @Override
    @Transactional
    public void register(RegisterParam param) throws Exception {
        System.out.println("注册参数："+param);
        System.out.println("注册参数手机号："+param.getMobile());
        //根据值获取redis中的验证码
        String code = redisUtil.getString(RedisKey.getSendRegCodeKey(param.getMobile()));
        System.out.println("验证码："+code);
        if(code==null){
            throw new RuntimeException("验证码已过期");
        }
        if(!code.equals(param.getCode())){
            throw new RuntimeException("验证码错误");
        }

        Account account = new Account();
        String s = UtilMD5.md5(param.getPassword(), param.getMobile());
        account.setName(param.getName());
        account.setPhone(param.getMobile());
        account.setPassword(s);
        account.setRoleId(StaticData.DEFAULT_ROLE_ID);
        account.setSex(param.getSex());
        account.setAge(param.getAge());
        account.setHeadPortrait(StaticData.DEFAULT_AVATAR);
        account.setReName("用户_"+param.getMobile());
        account.setRoleName(StaticData.DEFAULT_ROLE_NAME);
        accountMapper.insert(account);
        //获取主键回旋
        redisUtil.delete(RedisKey.getSendRegCodeKey(param.getMobile()));
        RoleAccount roleAccount = new RoleAccount();
        roleAccount.setAccountId(account.getId());
        roleAccount.setRoleId(StaticData.DEFAULT_ROLE_ID);
        roleAccountMapper.insert(roleAccount);
    }

    @Override
    public List<ResourceDto> login(LoginParam param, HttpServletResponse response) throws Exception {
        QueryWrapper<Account> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone",param.getAccount());
        Account account = accountMapper.selectOne(queryWrapper);
        if(account==null){
            throw new RuntimeException("账号不存在,请先注册");
        }
        if(!account.getPassword().equals(UtilMD5.md5(param.getPassword(), account.getPhone()))){
            throw new RuntimeException("密码错误");
        }
        //查询用户前端权限
        List<ResourceDto> resourceDtos= permissionService.selectPermissionByUserId(account.getId());
        //签发token
        Map<String, Object> map = BeanUtil.beanToMap(account);
        String accessToken = UtilJWP.createToken(map, 3 * 24 * 60 );
        //通过响应头将jwt响应给客户端
        System.out.println("token:"+accessToken);
        response.setHeader("token", accessToken);
        //在跨域请求访问时 必须公开该请求头 前端才能获取到
        response.setHeader("Access-Control-Expose-Headers", "token");
        System.out.println("登录成功");

//        String s1 = UtilMD5.md5("123456", "13456789001");
//        System.out.println("s1:"+s1);
        System.out.println("accountToken:"+accessToken);
        return resourceDtos;
    }

    @Override
    public String getUserInfo(Integer id) {

        QueryWrapper<Account> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id",id);
        Account account = accountMapper.selectOne(queryWrapper);
        if(account==null){
            return null;
        }
        return account.getName();
    }

    @Override
    public List<MerchantapplicationParam> viewTheApplication(String token) {
        Integer id = TokenTool.getUserIdByToken(token);
        Account account = accountMapper.selectById(id);
        if(account==null){
            throw new RuntimeException("用户不存在");
        }
        if (!account.getRoleName().equals(StaticData.PLATFORM_ADMINISTRATOR)){
            throw new RuntimeException("无权限查看");
        }
        Result result = centeencilent.viewTheApplicationList();
        List<MerchantapplicationParam> list = (List<MerchantapplicationParam>) result.getList();
        return list;
    }

    @Override
    public Integer getSuperAdminId() {
        QueryWrapper<Account> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("role_name",StaticData.PLATFORM_ADMINISTRATOR);
        Account account = accountMapper.selectOne(queryWrapper);
        if(account==null){
            throw new RuntimeException("超级管理员不存在");
        }
        return account.getId();
    }

    @Override
    public Account getUserInfoByMobile(String mobile) {

        QueryWrapper<Account> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone",mobile);
        Account account = accountMapper.selectOne(queryWrapper);
        if(account==null){
            throw new RuntimeException("手机号码不存在");
        }
        return account;
    }

    @Override
    public void updateUserInfo(Account account) {
        accountMapper.updateById(account);
    }

    @Override
    public List<Account> getAllRepairPerson() {
        List<Account> accounts = accountMapper.selectList(null);
        return accounts;
    }

    @Override
    public Account getUserInfoByToken(Integer id) {
        Account account = accountMapper.selectById(id);
        if(account==null){
            throw new RuntimeException("用户不存在");
        }
        return account;
    }

    @Override
    public List<Account> getAllUser(String token) {
        //解析token 获取用户id
        Integer id = TokenTool.getUserIdByToken(token);
        //判断是否为超级管理员
        Account account = accountMapper.selectById(id);
        if(account==null){
            throw new RuntimeException("用户不存在");
        }
        QueryWrapper<RoleAccount> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("role_id",1);
            queryWrapper.eq("account_id",id);
            RoleAccount roleAccount = roleAccountMapper.selectOne(queryWrapper);
            if(roleAccount==null){
                throw new RuntimeException("无权限查看");
            }
        //查询所有用户
        List<Account> accounts = accountMapper.selectList(null);
        return accounts;
    }

    @Override
    public void addAShoppingCart(AddAShoppingCartParam bean) throws Exception {
        Integer id = TokenTool.getUserIdByToken(bean.getToken());
        Account account = accountMapper.selectById(id);
        if(account==null){
            throw new RuntimeException("用户不存在");
        }
        //查询商品商品是否存在
        SelectProShopInfo selectProShopInfo = new SelectProShopInfo();
        selectProShopInfo.setShopId(bean.getShopId());
        selectProShopInfo.setProductId(bean.getProductId());
        Result result = centeencilent.queryProductDetail(selectProShopInfo);
        if(result.getData()==null){
            throw new RuntimeException("商品不存在");
        }
        ProductListForm productListForm = BeanUtil.copyProperties(result.getData(), ProductListForm.class);

        if (redisUtil.score(RedisKey.userCart(id), String.valueOf(bean.getProductId()))==null){
            //不存在就添加
            redisUtil.zadd(RedisKey.userCart(id), String.valueOf(bean.getProductId()) ,new Date().getTime());
            //将商品的信息放进HashMap中
            HashMap<String, String> map = new HashMap<>();
            map.put("productId", String.valueOf(productListForm.getId()));
            map.put("productName", productListForm.getProductName());
            map.put("shopId", String.valueOf(productListForm.getShopId()));
            map.put("picture", productListForm.getPicture());
            if(productListForm.getDiscountPrice() == null ||
                    productListForm.getDiscountPrice().compareTo(BigDecimal.ZERO) == 0){
                BigDecimal multiply = productListForm.getPrice().multiply(BigDecimal.valueOf(bean.getNumber()));
                map.put("price",String.valueOf(multiply));
            }else{
                BigDecimal decimal = productListForm.getPrice().multiply(BigDecimal.valueOf(bean.getNumber()));

                BigDecimal multiply = decimal.multiply(productListForm.getDiscountPrice());
                map.put("price",String.valueOf(multiply));
            }
            map.put("number", String.valueOf(bean.getNumber()));
            //当前的折扣
            map.put("discountPrice", String.valueOf(productListForm.getDiscountPrice()));
            //添加到redis中
            redisUtil.setHashMap(RedisKey.userCartOrder(id, bean.getProductId()), map);
        }else {
            //如果存在就重新计算价格
            //存在hashmap中自增
            redisUtil.hashIncrement(RedisKey.userCartOrder(id,bean.getProductId()), "number", bean.getNumber());
            HashMap<String, String> hashMapAll1 = new HashMap<>();
            HashMap<Object, Object> hashMapAll = redisUtil.getHashMapAll(RedisKey.userCartOrder(id, bean.getProductId()));
            BigDecimal number = new BigDecimal(hashMapAll.get("number").toString());
            if(productListForm.getDiscountPrice() == null ||productListForm.getDiscountPrice().compareTo(BigDecimal.ZERO) == 0){
                BigDecimal multiply = productListForm.getPrice().multiply(BigDecimal.valueOf(number.intValue()));
                //修改hashmap中键为price的值
                for (Map.Entry<Object, Object> entry : hashMapAll.entrySet()) {
                    if (entry.getKey().equals("price")) {
                       // 修改hashmap中键为price的值
                       entry.setValue(multiply.toString());
                    }
                }
                //删除原来的hashmap
                redisUtil.deleteHash(RedisKey.userCartOrder(id, bean.getProductId()));
                //存入redis中
                //将hashMapAll转成HashMap<String, String>
                HashMap<String, String> hashMapAll2 = new HashMap<>();
                for (Map.Entry<Object, Object> entry : hashMapAll.entrySet()) {
                    hashMapAll2.put(entry.getKey().toString(), entry.getValue().toString());
                }
                redisUtil.setHashMap(RedisKey.userCartOrder(id, bean.getProductId()), hashMapAll2);
            }else{
                BigDecimal decimal = productListForm.getPrice().multiply(BigDecimal.valueOf(number.intValue()));
                BigDecimal multiply = decimal.multiply(productListForm.getDiscountPrice());

                for (Map.Entry<Object, Object> entry : hashMapAll.entrySet()) {
                    if (entry.getKey().equals("price")) {
                        // 修改hashmap中键为price的值
                        entry.setValue(multiply.toString());
                    }
                }
                //删除原来的hashmap
                redisUtil.deleteHash(RedisKey.userCartOrder(id, bean.getProductId()));
                //存入redis中
                //将hashMapAll转成HashMap<String, String>
                HashMap<String, String> hashMapAll2 = new HashMap<>();
                for (Map.Entry<Object, Object> entry : hashMapAll.entrySet()) {
                    hashMapAll2.put(entry.getKey().toString(), entry.getValue().toString());
                }
                redisUtil.setHashMap(RedisKey.userCartOrder(id, bean.getProductId()), hashMapAll2);
            }

        }
    }

    @Override
    public void deleteShoppingCart(AddAShoppingCartParam bean) throws Exception {
        if(bean.getNumber()<1){
            throw new RuntimeException("数量不能小于1");
        }
        Integer id = TokenTool.getUserIdByToken(bean.getToken());
        Account account = accountMapper.selectById(id);
        if(account==null){
            throw new RuntimeException("用户不存在");
        }
        //判断购物车是否存在
        if (redisUtil.score(RedisKey.userCart(id), String.valueOf(bean.getProductId()))==null){
            throw new RuntimeException("购物车不存在");
        }
        //查询商品商品是否存在

        SelectProShopInfo selectProShopInfo = new SelectProShopInfo();
        selectProShopInfo.setShopId(bean.getShopId());
        selectProShopInfo.setProductId(bean.getProductId());
        Result result = centeencilent.queryProductDetail(selectProShopInfo);
        if(result.getData()==null){
            throw new RuntimeException("商品不存在");
        }
        ProductListForm productListForm = BeanUtil.copyProperties(result.getData(), ProductListForm.class);
        if (productListForm==null){
            throw new RuntimeException("商品不存在");
        }
        if(productListForm.getProductStatus()==StaticData.FOOD_STATUS_DOWN){
            throw new RuntimeException("该商品已下架");
        }
        int num = Integer.parseInt(redisUtil.getHashMap(RedisKey.userCartOrder(id, bean.getProductId()), "number"));
        if (num< bean.getNumber()) {
            throw new RuntimeException("减少的数量大于购物车中数量");
        }
        if (num == bean.getNumber()) {
            //如果相等就将对应的hashmap删除
            //删除自己zset中的元素
            redisUtil.zrem(RedisKey.userCart(id), String.valueOf(bean.getProductId()));
            //删除对应的hashmap
            redisUtil.deleteHashMap(RedisKey.userCartOrder(id, bean.getProductId()));

        } else {
            //减少数量

            int num1 = Integer.parseInt(redisUtil.getHashMap(RedisKey.userCartOrder(id, bean.getProductId()), "number"));
            if (num1 == 1) {
                //删除hashmap
                redisUtil.delete(RedisKey.userCartOrder(id, bean.getProductId()));
                //删除zset中的元素
                redisUtil.zrem(RedisKey.userCart(id), String.valueOf(bean.getProductId()));
            }else if (num1 > 1) {
                redisUtil.hashIncrement(RedisKey.userCartOrder(id, bean.getProductId()), "number",-bean.getNumber());
            }
        }
    }

    @Override
    public PageInfo<UserCartInfoForm> MyShoppingCart(String token, PageForm pageParam) throws Exception {

        Integer userId = TokenTool.getUserIdByToken(token);
        PageInfo<UserCartInfoForm> pageInfo=new PageInfo<>();
        pageInfo.setPages(0);
        pageInfo.setPageNum(pageParam.getPageNum());
        pageInfo.setPageSize(pageParam.getPageSize());
        pageInfo.setTotal(0);
        ArrayList<UserCartInfoForm> list = new ArrayList<>();
        pageInfo.setList(list);

        if (redisUtil.hasKey(RedisKey.userCart(userId))) {
            //存在就直接返回
            Set<String> zrevrange = redisUtil.zrevrange(RedisKey.userCart(userId), (pageParam.getPageNum() - 1) * pageParam.getPageSize(), pageParam.getPageNum() * pageParam.getPageSize());
            //查询购物车总数
            long total = redisUtil.zcard(RedisKey.userCart(userId));
            long pages = total % pageParam.getPageSize() == 0 ? total / pageParam.getPageSize() : total / pageParam.getPageSize() + 1;
            pageInfo.setPages((int) pages);
            pageInfo.setTotal((int) total);
            //查询购物车信息
            for (String productId : zrevrange) {
                HashMap<Object, Object> hashMapAll = redisUtil.getHashMapAll(RedisKey.userCartOrder(userId, Integer.parseInt(productId)));
                UserCartInfoForm myShoppingCartDto = BeanUtil.mapToBean(hashMapAll, UserCartInfoForm.class, true);
                list.add(myShoppingCartDto);
            }
        }
        return pageInfo;

    }

    @Override
    public Account getUserInfoById(Integer id) {
        if (id!=null){
            Account account = accountMapper.selectById(id);
            return account;
        }
        return null;
    }

    @Override
    public void addMerchant(AccountForm accountForm) {
        Account bean = BeanUtil.toBean(accountForm, Account.class);
        accountMapper.insert(bean);
        RoleAccount roleAccount = new RoleAccount();
        roleAccount.setAccountId(bean.getId());
        roleAccount.setRoleId(StaticData.SHOP_ROLE_ID);
        roleAccountMapper.insert(roleAccount);
    }


}
